package com.duowan.cms.service.file;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.commons.fileupload.FileItem;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.duowan.cms.common.util.ChineseCharactersUtil;
import com.duowan.cms.common.util.DispatchFileUtil;
import com.duowan.cms.common.util.FileUtil;
import com.duowan.cms.common.util.ProcessUtil;
import com.duowan.cms.common.util.StringUtil;
import com.duowan.cms.common.webapp.property.ExtendedPropertyPlaceholderConfigurer.PropertiesHolder;
import com.duowan.cms.dto.channel.ChannelInfo;
import com.duowan.cms.service.channel.ChannelService;

@Service("fileService")
public class FileServiceImpl implements FileService {
	private static Logger logger = Logger.getLogger(FileServiceImpl.class);
	
	private static List<String> imgIpList = new ArrayList<String>();
	
	private static List<String> nginxSourceIpList = new ArrayList<String>();
	
	@Autowired
	private ChannelService channelService;
	
	static{
		String IMG_DWSTATIC_IPS = PropertiesHolder.get("img_dwstatic_ips");
		String ipArr[] =IMG_DWSTATIC_IPS.split(";");
		for (int i = 0; i < ipArr.length; i++) {
			if (!"".equals(ipArr[i])) {
				imgIpList.add(ipArr[i]);
			}
		}
		String NGINX_SOURCE_IPS = PropertiesHolder.get("nginx_source_ips");
		String nginxSourceArr[] =NGINX_SOURCE_IPS.split(";");
		for (int i = 0; i < nginxSourceArr.length; i++) {
			if (!"".equals(nginxSourceArr[i])) {
				nginxSourceIpList.add(nginxSourceArr[i]);
			}
		}
	}
	
	@Override
	public boolean deleteFile(String path) {
		logger.info("删除路径[" + path +"]下的文件");
        File file = new File(path);  
        if(file.exists() && file.isFile()) {
        	return file.delete();
        }else if(file.exists() && file.isDirectory()) {  
        	return deleteDirectory(file);
        }  
        return true;
	}
	
	@Override
	public void deleteFileByUrl(String channelId , String url) {
		ChannelInfo channelInfo = channelService.getById(channelId);
		logger.info("根据URL["+url+"]删除["+channelInfo.getName()+"]频道在服务器上的文件");
		String picPath = channelInfo.getPicFilePath() + url.substring(url.indexOf(channelId)+channelId.length());
		this.deleteFile(picPath);
	}


	/**
	 * 此算法若遇到性能问题，可优化
	 */
	@Override
	public FileAdapter[] sortFile(FileAdapter[] fileAdapterArr) {
		List<FileAdapter> directoryList = new ArrayList<FileAdapter>();//目录集合
		List<FileAdapter> fileList = new ArrayList<FileAdapter>();//文件集合
		for (int i = 0; i < fileAdapterArr.length; i++) {//先把文件分成目录集合和文件集合
			if (fileAdapterArr[i].isDirectory()) {
				directoryList.add(fileAdapterArr[i]);
			}else{
				fileList.add(fileAdapterArr[i]);
			}
		}
		Collections.sort(directoryList, new Comparator<FileAdapter>(){//目录集合排序
            @Override
            public int compare(FileAdapter o1, FileAdapter o2) {
                String name1 = ChineseCharactersUtil.String2Alpha(o1.getName());
                String name2 = ChineseCharactersUtil.String2Alpha(o2.getName());
                return name1.compareTo(name2);
            }
        });
		Collections.sort(fileList, new Comparator<FileAdapter>(){//文件集合排序
            @Override
            public int compare(FileAdapter o1, FileAdapter o2) {
                String name1 = ChineseCharactersUtil.String2Alpha(o1.getName());
                String name2 = ChineseCharactersUtil.String2Alpha(o2.getName());
                return name1.compareTo(name2);
            }
        });
		FileAdapter[] resultFileAdapter = new FileAdapter[fileAdapterArr.length];//合并两个集合
		for (int i = 0; i < directoryList.size(); i++) {
			resultFileAdapter[i] = directoryList.get(i);
		}
		for (int j = 0; j < fileList.size(); j++) {
			resultFileAdapter[j+directoryList.size()] = fileList.get(j);
		}
		return resultFileAdapter;
	}
	
	

	@Override
	public void rsycFile(String destDir, String currentPath, String channelId) {
		File file = new File(destDir);
		if (file.isFile()) {
			logger.info("同步[" + destDir + "]文件到外网");
			this.executeRsyncCommand(destDir, currentPath, channelId);
		}else{
			File []fileArr = file.listFiles();
			for (int i = 0; i < fileArr.length; i++) {
				this.rsycFile(fileArr[i].getAbsolutePath(), currentPath, channelId);
			}
		}
	}
	/**
	 * 	执行同步命令 
	 * 带有工作空间的rsync命令（工作空间：/data2/www/cms.duowan.com/wow , wow是指channelId）
	 * "rsync -avzR--password-file=/etc/rsyncd_users_tomcat "+ src_file + "  release@" + ip + "::cms_release_code/"+channelId+".duowan.com/"+ dest_file;
	 */
	private void executeRsyncCommand(String destDir, String currentPath, String channelId){
		String command = "rsync -avzR --password-file=/etc/rsyncd_users_tomcat " ;
		ChannelInfo channelInfo = channelService.getById(channelId);
		
		logger.debug("执行rsync命令同步【"+destDir+"】目录的文件"  );
	      if(FileUtil.isPicFormat(destDir ) && ( currentPath.indexOf(FileUtil.getFilePath("/s/")) == -1 )){//非/s/目录的图片同步到图片服务器
	    	  //经过与汪千斯迪的商量，暂时把图片服务器的rync命令注释掉
//	  		String basePath = channelInfo.getPicFilePath();
//	  		String relativePath = FileUtil.getFilePath(destDir.substring(destDir.indexOf(basePath) + basePath.length() +1)) ;
//		  		for (int i = 0; i < imgIpList.size(); i++) {
//		  		    String 	exeCommand = command + imgIpList.get(i) + "::cms_release_code/"+channelInfo.getId()+".duowan.com/"  + relativePath;
//		  			logger.debug("执行rsync命令:" + exeCommand);
//					ProcessUtil.execute(exeCommand);
//				}
	      }else{
		  		String basePath = channelInfo.getArticleFilePath();
		  		String relativePath = FileUtil.getFilePath(destDir.substring(destDir.indexOf(basePath) + basePath.length() + 1)) ;
		  		for (int i = 0; i < nginxSourceIpList.size(); i++) {
//		  			String 	exeCommand = command + nginxSourceIpList.get(i) + "::cms_release_code/"+channelInfo.getId()+".duowan.com/" + relativePath;
//					ProcessUtil.execute(exeCommand);
		  			String 	exeCommand = command + relativePath + " release@" + nginxSourceIpList.get(i) + "::cms_release_code/"
		  							+channelInfo.getId()+".duowan.com/" ;
		  			logger.info("执行rsync命令:" + exeCommand.replace("\\", "/") +",工作空间:" + basePath );
		  			ProcessUtil.execute(exeCommand.replace("\\", "/") , basePath );
		  			
				}
	      }   
	}


	@Override
	public void dispatchFile(String destDir, String currentPath, String channelId) {
		
		File file = new File(destDir);
		File []fileArr = file.listFiles();
		logger.info("分发[" + destDir + "]目录的文件");
	    for (int i = 0; i < fileArr.length; i++) {
	        File sonFile = fileArr[i];
            if (sonFile.isFile()) {   
            	String dispatchPath = this.getDispatchPath(sonFile, currentPath, channelId);
	      	    if (FileUtil.getFilePath(sonFile.getAbsolutePath()).indexOf(dispatchPath) == -1) {//相同路径不移动
	      	    	dispatchPath = dispatchPath.substring(0, dispatchPath.lastIndexOf(System.getProperty("file.separator")));
	      	    	logger.info("把文件["+sonFile.getName()+"]从目录["+sonFile.getAbsolutePath()+"]移动到["+dispatchPath+"]目录" );
	      	    	File targetFile = new File(dispatchPath);
	      	    	if (!targetFile.exists() ) {
	      	    		targetFile.mkdirs();
					}
	      	    	try {
						DispatchFileUtil.dispatch(sonFile.getAbsolutePath(), dispatchPath);
					} catch (Exception e) {
						logger.error("移动文件失败");
					} 
				}
            }else if (sonFile.isDirectory()) {
            	this.dispatchFile(sonFile.getAbsolutePath(), currentPath , channelId);
            }
        }
	}
	/**
	 *  获取分发的路径 
	 * @return
	 */
	private String getDispatchPath(File sonFile , String currentPath , String channelId){
		ChannelInfo channelInfo = channelService.getById(channelId);
	     String articleFilePath = channelInfo.getArticleFilePath();
	     String picFilePath =  channelInfo.getPicFilePath();
	      if(FileUtil.isPicFormat( sonFile.getName() ) && ( currentPath.indexOf(FileUtil.getFilePath("/s/")) == -1 )){
	    	  return  FileUtil.getFilePath(sonFile.getAbsolutePath().replace(articleFilePath , picFilePath ));
	      }   
	     return  FileUtil.getFilePath(sonFile.getAbsolutePath());
	}

	/**
	 * 
	 */
	@Override
	public void writeFile(FileItem item, String basePath) throws Exception {
		this.writeFile(item, basePath, "");
	}


	@Override
	public void writeFile(FileItem item, String basePath , String randomFileName) throws Exception {
		
		 File basePathFile = new File(basePath);
		 if (!basePathFile.exists()) {//若根目录不存在，则创建根目录
			 basePathFile.mkdirs();
		 }
		 String itemName ;
		 if (!StringUtil.isEmpty(randomFileName)) {
			 itemName = randomFileName;
		}else{
			itemName = FileUtil.getFileNameByFileItem(item);
		}
		
		item.write(new File(basePath + FileUtil.FILE_SEPARATOR + itemName));
		logger.info("写文件路径：" + basePath + FileUtil.FILE_SEPARATOR + itemName);
	}
	
	
	
	@Override
	public List<FileAdapter> searchFileByName(FileAdapter searchFile, String name) {
		//logger.debug("在文件["+searchFile.getAbsolutePath()+"]内部，根据文件名["+name+"]查找文件");
	    List<FileAdapter> resultFileList = new ArrayList<FileAdapter>();
	    FileAdapter fileArr[] = searchFile.listFiles();
	    for (int i = 0; i < fileArr.length; i++) {
	        FileAdapter fileAdapter = fileArr[i];
            if (fileAdapter.isFile() && fileAdapter.getName().indexOf(name)>-1) {   //加入结果文件
                resultFileList.add(fileAdapter);
            }else if (fileAdapter.isDirectory()) {
                if (fileAdapter.getName().indexOf(name) >-1) {//加入结果目录
                    resultFileList.add(fileAdapter);
                }
                //不作深度搜索，只搜索当前目录，不搜索其子目录
//                List<FileAdapter> subResult = this.searchFileByName(fileAdapter, name);
//                if (subResult != null) {
//                    resultFileList.addAll(subResult);
//                }
            }
        }
        return resultFileList;
    }
	



	@Override
	public void createFolder(String path) {
		logger.info("创建目录:" +path);
		File file = new File(path);
		if (!file.exists()) {
			file.mkdirs();
		}
	}



	/**
	 * 删除目录
	 * @param file
	 */
    private  boolean deleteDirectory(File file){
    	logger.info("删除目录：" + file.getAbsolutePath());
    	boolean isDeleteSuccess = true ;
        //删除文件夹的内容  
        File[] files = file.listFiles();  
        for(File tempFile : files) {  
        	if ( tempFile.exists() ) {
        		//只有所有文件删除成功才返回true
        		isDeleteSuccess = isDeleteSuccess && deleteFile(tempFile.getAbsolutePath());  
			}
        }  
        if (file.exists()) {
            //删除空文件夹  
            isDeleteSuccess = isDeleteSuccess && file.delete();
		}
        return isDeleteSuccess;
    }
}
